home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / handler.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  27KB  |  1,161 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22. #include <ctype.h>
  23. #include <sys/wait.h>
  24. #include <sys/stat.h>
  25.  
  26. #include "mutt.h"
  27. #include "mutt_curses.h"
  28. #include "rfc1524.h"
  29. #include "keymap.h"
  30. #include "mime.h"
  31. #include "state.h"
  32. #include "parse.h"
  33.  
  34. #ifdef _PGPPATH
  35. #include "pgp.h"
  36. #endif
  37.  
  38. typedef void handler_f (BODY *, STATE *);
  39. typedef handler_f *handler_t;
  40.  
  41. int Index_hex[128] = {
  42.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  43.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  44.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  45.      0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
  46.     -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  47.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  48.     -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  49.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
  50. };
  51.  
  52. int Index_64[128] = {
  53.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  54.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
  55.     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
  56.     52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
  57.     -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
  58.     15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
  59.     -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
  60.     41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
  61. };
  62.  
  63. void mutt_decode_xbit (STATE *s, long len, int istext)
  64. {
  65.   int linelen;
  66.   char buffer[LONG_STRING];
  67.  
  68.   if (istext)
  69.   {
  70.     while (len > 0)
  71.     {
  72.       if (fgets (buffer, LONG_STRING, s->fpin) == 0) return;
  73.       linelen = strlen (buffer);
  74.       len -= linelen;
  75.       if (linelen >= 2 && buffer[linelen-2] == '\r')
  76.       {
  77.     buffer[linelen-2] = '\n';
  78.     buffer[linelen-1] = 0;
  79.       }
  80.       if (s->prefix) state_puts (s->prefix, s);
  81.       state_puts (buffer, s);
  82.     }
  83.   }
  84.   else
  85.     mutt_copy_bytes (s->fpin, s->fpout, len);
  86. }
  87.  
  88. void mutt_decode_quoted (STATE *s, long len, int istext)
  89. {
  90.   char *c, buffer[LONG_STRING];
  91.   int ch, soft = 0;
  92.  
  93.   while (len > 0)
  94.   {
  95.     if (fgets (buffer, LONG_STRING, s->fpin) == NULL)
  96.     {
  97.       dprint (1, (debugfile, "mutt_decode_quoted: unexpected EOF.\n"));
  98.       state_puts ("[-- Error: unexpected end of file! --]\n", s);
  99.       break;
  100.     }
  101.     c = buffer;
  102.     len -= strlen (buffer);
  103.     if (s->prefix && !soft) state_puts (s->prefix, s);
  104.     soft = 0;
  105.     while (*c)
  106.     {
  107.       if (*c == '=')
  108.       {
  109.         if (c[1] == '\n' || c[1] == '\r' || c[1] == ' ' || c[1] == '\t')
  110.     {
  111.           /* Skip whitespace at the end of the line since MIME does not
  112.            * allow for it
  113.        */
  114.           soft = 1;
  115.           break;
  116.         }
  117.         ch = hexval ((int) c[1]) << 4;
  118.         ch |= hexval ((int) c[2]);
  119.         state_putc (ch, s);
  120.         c += 3;
  121.       }
  122.       else if (istext && c[0] == '\r' && c[1] == '\n')
  123.       {
  124.         state_putc ('\n', s);
  125.         break;
  126.       }
  127.       else
  128.       {
  129.         state_putc (*c, s);
  130.         c++;
  131.       }
  132.     }
  133.   }
  134. }
  135.  
  136. void mutt_decode_base64 (STATE *s, long len, int istext)
  137. {
  138.   char buf[5];
  139.   int c1, c2, c3, c4, ch, cr = 0, i;
  140.  
  141.   buf[4] = 0;
  142.  
  143.   if (s->prefix) state_puts (s->prefix, s);
  144.  
  145.   while (len > 0)
  146.   {
  147.     for (i = 0 ; i < 4 && len > 0 ; len--)
  148.     {
  149.       if ((ch = fgetc (s->fpin)) == EOF)
  150.     return;
  151.       if (!ISSPACE (ch))
  152.     buf[i++] = ch;
  153.     }
  154.     if (i != 4)
  155.       return; /* didn't get a multiple of four chars! */
  156.  
  157.     c1 = base64val ((int) buf[0]);
  158.     c2 = base64val ((int) buf[1]);
  159.     ch = (c1 << 2) | (c2 >> 4);
  160.  
  161.     if (cr && ch != '\n') state_putc ('\r', s);
  162.     cr = 0;
  163.       
  164.     if (istext && ch == '\r')
  165.       cr = 1;
  166.     else
  167.     {
  168.       state_putc (ch, s);
  169.       if (ch == '\n' && s->prefix) state_puts (s->prefix, s);
  170.     }
  171.  
  172.     if (buf[2] == '=')
  173.       break;
  174.     c3 = base64val ((int) buf[2]);
  175.     ch = ((c2 & 0xf) << 4) | (c3 >> 2);
  176.  
  177.     if (cr && ch != '\n')
  178.       state_putc ('\r', s);
  179.     cr = 0;
  180.  
  181.     if (istext && ch == '\r')
  182.       cr = 1;
  183.     else
  184.     {
  185.       state_putc (ch, s);
  186.       if (ch == '\n' && s->prefix)
  187.     state_puts (s->prefix, s);
  188.     }
  189.  
  190.     if (buf[3] == '=') break;
  191.     c4 = base64val ((int) buf[3]);
  192.     ch = ((c3 & 0x3) << 6) | c4;
  193.  
  194.     if (cr && ch != '\n')
  195.       state_putc ('\r', s);
  196.     cr = 0;
  197.  
  198.     if (istext && ch == '\r')
  199.       cr = 1;
  200.     else
  201.     {
  202.       state_putc (ch, s);
  203.       if (ch == '\n' && s->prefix)
  204.     state_puts (s->prefix, s);
  205.     }
  206.   }
  207. }
  208.  
  209. /* ----------------------------------------------------------------------------
  210.  * A (not so) minimal implementation of RFC1563.
  211.  */
  212.  
  213. #define IndentSize (4)
  214.     
  215. enum { RICH_PARAM=0, RICH_BOLD, RICH_UNDERLINE, RICH_ITALIC, RICH_NOFILL, 
  216.   RICH_INDENT, RICH_INDENT_RIGHT, RICH_EXCERPT, RICH_CENTER, RICH_FLUSHLEFT,
  217.   RICH_FLUSHRIGHT, RICH_COLOR, RICH_LAST_TAG };
  218.  
  219. static struct {
  220.   const char *tag_name;
  221.   int index;
  222. } EnrichedTags[] = {
  223.   { "param",        RICH_PARAM },
  224.   { "bold",        RICH_BOLD },
  225.   { "italic",        RICH_ITALIC },
  226.   { "underline",    RICH_UNDERLINE },
  227.   { "nofill",        RICH_NOFILL },
  228.   { "excerpt",        RICH_EXCERPT },
  229.   { "indent",        RICH_INDENT },
  230.   { "indentright",    RICH_INDENT_RIGHT },
  231.   { "center",        RICH_CENTER },
  232.   { "flushleft",    RICH_FLUSHLEFT },
  233.   { "flushright",    RICH_FLUSHRIGHT },
  234.   { "flushboth",    RICH_FLUSHLEFT },
  235.   { "color",        RICH_COLOR },
  236.   { "x-color",        RICH_COLOR },
  237.   { NULL,        -1 }
  238. };
  239.  
  240. struct enriched_state
  241. {
  242.   char *buffer;
  243.   char *line;
  244.   char *param;
  245.   size_t buff_len;
  246.   size_t line_len;
  247.   size_t line_used;
  248.   size_t indent_len;
  249.   size_t word_len;
  250.   size_t buff_used;
  251.   size_t param_len;
  252.   int tag_level[RICH_LAST_TAG];
  253.   int WrapMargin;
  254.   STATE *s;
  255. };
  256.  
  257. static void enriched_wrap (struct enriched_state *stte)
  258. {
  259.   int x;
  260.   int extra;
  261.  
  262.   if (stte->line_len)
  263.   {
  264.     if (stte->tag_level[RICH_CENTER] || stte->tag_level[RICH_FLUSHRIGHT])
  265.     {
  266.       /* Strip trailing white space */
  267.       size_t y = stte->line_used - 1;
  268.  
  269.       while (y && ISSPACE (stte->line[y]))
  270.       {
  271.     stte->line[y] = '\0';
  272.     y--;
  273.     stte->line_used--;
  274.     stte->line_len--;
  275.       }
  276.       if (stte->tag_level[RICH_CENTER])
  277.       {
  278.     /* Strip leading whitespace */
  279.     y = 0;
  280.  
  281.     while (stte->line[y] && ISSPACE (stte->line[y]))
  282.       y++;
  283.     if (y)
  284.     {
  285.       size_t z;
  286.  
  287.       for (z = y ; z <= stte->line_used; z++)
  288.       {
  289.         stte->line[z - y] = stte->line[z];
  290.       }
  291.  
  292.       stte->line_len -= y;
  293.       stte->line_used -= y;
  294.     }
  295.       }
  296.     }
  297.  
  298.     extra = stte->WrapMargin - stte->line_len - stte->indent_len -
  299.       (stte->tag_level[RICH_INDENT_RIGHT] * IndentSize);
  300.     if (extra > 0) 
  301.     {
  302.       if (stte->tag_level[RICH_CENTER]) 
  303.       {
  304.     x = extra / 2;
  305.     while (x)
  306.     {
  307.       state_putc (' ', stte->s);
  308.       x--;
  309.     }
  310.       } 
  311.       else if (stte->tag_level[RICH_FLUSHRIGHT])
  312.       {
  313.     x = extra-1;
  314.     while (x)
  315.     {
  316.       state_putc (' ', stte->s);
  317.       x--;
  318.     }
  319.       }
  320.     }
  321.     state_puts (stte->line, stte->s);
  322.   }
  323.  
  324.   state_putc ('\n', stte->s);
  325.   stte->line[0] = '\0';
  326.   stte->line_len = 0;
  327.   stte->line_used = 0;
  328.   stte->indent_len = 0;
  329.   if (stte->s->prefix)
  330.   {
  331.     state_puts (stte->s->prefix, stte->s);
  332.     stte->indent_len += strlen (stte->s->prefix);
  333.   }
  334.  
  335.   if (stte->tag_level[RICH_EXCERPT])
  336.   {
  337.     x = stte->tag_level[RICH_EXCERPT];
  338.     while (x) 
  339.     {
  340.       if (stte->s->prefix)
  341.       {
  342.     state_puts (stte->s->prefix, stte->s);
  343.         stte->indent_len += strlen (stte->s->prefix);
  344.       }
  345.       else
  346.       {
  347.     state_puts ("> ", stte->s);
  348.     stte->indent_len += strlen ("> ");
  349.       }
  350.       x--;
  351.     }
  352.   }
  353.   else
  354.     stte->indent_len = 0;
  355.   if (stte->tag_level[RICH_INDENT])
  356.   {
  357.     x = stte->tag_level[RICH_IN